/**
 * 
 */
package edu.cmu.vlis.wassup;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;
import java.lang.management.*;


/**
 * This class listens to coordinator and starts the process on coordinator's request. 
 */
public class ProcessManager {

    private ServerSocket socket;
    private Socket clientSocket;
    private PrintWriter out;
    private BufferedReader reader;
    private int _port;

    public ProcessManager() {

        this._port = 50000;
        
        try {
            this.socket = new ServerSocket(this._port);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void initialize(){
        System.out.println("Trying to establish the connection with coordinator..");
        try {
            this.socket = new ServerSocket(this._port);
            this.clientSocket = this.socket.accept();
            this.out = new PrintWriter(clientSocket.getOutputStream(), true);
            this.reader = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));
            System.out.println("Connection established with Coordinator.");

        } catch (IOException e1) {
            e1.printStackTrace();
        }
    }

    private void listenToCoordinator(){
        String line;
        while(true){
            try {
                Thread.sleep(1000);
                line = this.reader.readLine(); 
                System.out.println("PM rcvd from coordinator: "+line);
                if(line.equals("ALIVE?")){

                    this.out.println("Yes");
                    this.out.flush();
                    continue;
                }
                if(line.contains(":")){
                    System.err.println("Signal recvd.. Attempting to start process with process Id: "+line);
                    String[] parts = line.split(":");
                    boolean res = this.startProcess(parts[0],parts[1]);
                    if(res)
                        this.out.println("Yes");
                    else
                        this.out.println("No");
                    this.out.flush();                    
                }

            } catch (IOException e) {
                e.printStackTrace();
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }catch (NullPointerException npe){
                npe.printStackTrace();
//                if ( !clientSocket.isBound() || clientSocket.isClosed() || !clientSocket.isConnected() || clientSocket.isInputShutdown() || clientSocket.isOutputShutdown()){
                    System.out.println("Connection with coordinator is lost..");
                    this.initialize();
//                }
            }
        }
    }

    public boolean startProcess(String topic,String port){
        
        String javaLoc = new File(System.getProperty("java.home")).getParent()+File.separator+"bin"+File.separator+"java";
        ProcessBuilder pb = new ProcessBuilder(javaLoc,"-cp", System.getProperty("java.class.path"), "edu.cmu.vlis.wassup.ProcessFactory",topic,port);
        pb.directory(new File(System.getProperty("user.dir")));
        pb.redirectErrorStream(true);
        try {
            Process p = pb.start();
            OutputStream os = p.getOutputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
            String line;
            os.flush();
            while((line = br.readLine()) != null){
                os.flush();
                System.out.println(line);
                if(line.contains("Successfully started: "))
                    return true;
                if(line.contains("Exception"))
                    return false;
            }
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        return false;
    }

    public static void main(String[] args) {
        ProcessManager pm = new ProcessManager();
        System.out.println("Process Manager successfully started");
        pm.initialize();
        pm.listenToCoordinator();
    }
}
